﻿using FlowCanvas;
using ImageEffects;
using LogSystem;
using NodeCanvas.Framework;
using System;
using com.yoozoo.gta;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.Playables;
using Yoozoo.Core.Timeline;
using Yoozoo.Gameplay.City;
using Yoozoo.Gameplay.Liberty.AI;
using Yoozoo.Gameplay.Liberty.AI.Utils;
using Yoozoo.Gameplay.Liberty.Nodes;
using Yoozoo.Gameplay.Liberty.PlayerController;
using Yoozoo.Gameplay.Liberty.Pool;
using Yoozoo.Gameplay.Liberty.StreetEvent;

namespace Yoozoo.Gameplay.Liberty
{
    public static class LuaCallFunctions
    {
        public static void InitBlueprintPointConfig(TextAsset json)
        {
            BluePrintPoints bluePrintPoint = JsonUtility.FromJson<BluePrintPoints>(json.text);
            BlueprintUtils.BlueprintPoints = bluePrintPoint.Data;
            
            // 初始化蓝图管理器
            //BlueprintUtils.TimelineManager = new TimelineManager();
        }

        public static void SetObject2Point(GameObject o, string pointName)
        {
            var point = BlueprintUtils.GetBlueprintPoint(pointName);
            if (point == null)
            {
                Debug.LogError(LogModule.LibertyScene,"没有这个点：" + pointName);
                return;
            }

            o.transform.position = point.position;
            o.transform.eulerAngles = point.eulerAngles;
            if (o.transform.parent)
            {
                var p = o.transform.parent;
                o.transform.parent = null;
                o.transform.localScale = point.lossyScale;
                o.transform.parent = p;
            }
            else
            {
                o.transform.localScale = point.lossyScale;
            }
            //o.transform.forward = point.forward;
        }
        
        public static void InitMainController(GameObject controller)
        {
            BlueprintUtils.PlayerController = controller.GetComponent<PlayerControlModeMgr>();
            LibertyAIUtils.PlayerCamera = BlueprintUtils.GetPlayerCamera();
        }

        public static void InitTrafficSystem(LibertyTrafficData trafficData, Action callBack)
        {
            LibertyAIUtils.TrafficManager.Preload(trafficData,callBack);
        }

        public static void DisposeTrafficSystem()
        {
            //LibertyAIUtils.TrafficManager.Dispose();
            LibertyAIUtils.TrafficManager = null;
            AIGraphUtils.TrafficManager = null;
        }

        public static void SwitchCarSystemState(bool enable, bool excludePlayerCar)
        {
            if (enable) {
                LibertyAIUtils.AIManager.CarBirthManager.EnableAllCar(excludePlayerCar);
            }
            else {
                LibertyAIUtils.AIManager.CarBirthManager.DisableAllCar(excludePlayerCar);
            }
        }

        public static void SwitchNpcSystemState(bool enable)
        {
            if (enable) {
                LibertyAIUtils.AIManager.NpcBirthManager.EnableAllNpc();
            }
            else {
                LibertyAIUtils.AIManager.NpcBirthManager.DisableAllNpc();
            }
        }

        public static void PlayTimeline(string name,Action onStop,Action onStart, Transform parent, GameObject changeModel)
        {
            BlueprintUtils.PlayTimeline(name,(director =>
            {
                onStop?.Invoke();
            }),(director =>
            {
                // 目前内城补充体力事件timeline需要替换英雄模型
                if (changeModel)
                {
                    changeModel.transform.parent = director.transform;
                    changeModel.transform.localPosition = Vector3.zero;
                    changeModel.transform.localScale = new Vector3(1.89f,1.89f,1.89f);
                    changeModel.transform.localEulerAngles = Vector3.zero;
                    var changeControl = director.GetComponent<TimelineChangeModel>();
                    if (changeControl)
                    {
                        var ani = changeModel.GetComponentInChildren<Animator>();
                        changeControl.SetGenericBindAni(ani);
                    }
                }
                onStart?.Invoke();
                
            }),null, DirectorWrapMode.None,"","",0,parent);
        }

        public static void StopTimeline(string name)
        {
            BlueprintUtils.TimelineManager?.StopTimeline(name);
        }
        
        public static void StartAllBlueprint(GameObject root)
        {
            var controllers = root.GetComponentsInChildren<FlowScriptController>();
            foreach (var controller in controllers)
            {
                if (!controller.graph.isRunning)
                {
                    controller.StartBehaviour();
                }
            }
        }

        public static void PauseAllBlueprint(GameObject root)
        {
            var controllers = root.GetComponentsInChildren<FlowScriptController>();
            foreach (var controller in controllers)
            {
                controller.PauseBehaviour();
            }
        }

        public static void ResumeAllBlueprint(GameObject root)
        {
            var controllers = root.GetComponentsInChildren<FlowScriptController>();
            foreach (var controller in controllers)
            {
                controller.StartBehaviour();
            }
        }
        
        public static void ClearAllAI()
        {
            // LibertyAIUtils.AIManager.Clear();
            // PathPool.ClearPool();
        }

        // 销毁当前所有Npc和车辆，准备重新生成
        public static void ClearCurrentAI()
        {
            LibertyAIUtils.AIManager.ClearCurrentAI();
        }

        public static void SetRpgLightController(LightController lightController)
        {
            LibertyAIUtils.AIManager.NpcBirthManager.lightController = lightController;
            LibertyAIUtils.AIManager.CarBirthManager.lightController = lightController;
        }

        public static void SetTimelineRenderScene(GameObject freeRenderScene)
        {
            TimelineUtils.FreeRenderScene = freeRenderScene;
        }

        public static void OnEnterCityScene(int sceneType)
        {
            if (sceneType == 2)  // 挂机 DEBUG
            {
               

            }
            
        }

        public static void OnExitCityScene()
        {
            BlueprintUtils.ClearLuaFunction();
            TimelineUtils.ClearLuaFunction();
            
        }

        public static void AddAllCar()
        {
            // for (int i = 0; i < 7; i++)
            // {
            //     CarBirthData birthData = new CarBirthData();
            //     birthData.random = true;
            //     birthData.splineId = 1;
            //     birthData.uniqueId = i;
            //     birthData.customPos = true;
            //     birthData.pos = i * 75 + UnityEngine.Random.Range(0,15);
            //     LibertyAIUtils.AIManager.CarBirthManager.AddCar(birthData);
            //     
            // }
            //     
            // for (int i = 0; i < 7; i++)
            // {
            //     CarBirthData birthData = new CarBirthData();
            //     birthData.random = true;
            //     birthData.splineId = 2;
            //     birthData.uniqueId = i + 100;
            //     birthData.customPos = true;
            //     birthData.pos = i * 80 + UnityEngine.Random.Range(0,15);
            //     LibertyAIUtils.AIManager.CarBirthManager.AddCar(birthData);
            //     
            // }

        }
        
        
        public static void OnRpgLevelComplete(int levelId)
        {
            BlueprintEvents.SendRpgLevelComplete(levelId);
        }

        public static void OnRpgLevelFailed(int levelId)
        {
            BlueprintEvents.SendRpgLevelFailed(levelId);
        }

        public static void OnSurvivorLevelComplete(int levelId)
        {
            BlueprintEvents.SendSurvivorMissionComplete(levelId);
        }
        
        public static void OnSurvivorLevelFailed(int levelId)
        {
            BlueprintEvents.SendSurvivorMissionFailed(levelId);
        }
        
        public static void OnDialogueComplete(int dialogueId)
        {
            BlueprintEvents.SendDialogueComplete(dialogueId);
        }

        public static void OnOccupyEffectComplete(int streetId)
        {
            BlueprintEvents.SendOccupyEffectComplete(streetId);
        }

        public static void OnGuideEvent(int eventId)
        {
            BlueprintEvents.SendGuideEvent(eventId);
        }

        public static void OnServerResponse(string respName, string key, string val)
        {
            BlueprintEvents.SendServerResponseEvent(respName, key, val);
        }

        public static void OnGlobalEvent(string eventName)
        {
            if (string.IsNullOrEmpty(eventName))
            {
                Debug.LogError(LogModule.Blueprint,"派发蓝图全局事件失败，事件名为空~");
                return;
            }
            Graph.SendGlobalEvent(eventName, null, null);
        }

        public static void AddRecord(string record)
        {
            if (BlueprintUtils.RecordList.Contains(record))
            {
                //Debug.LogWarning(LogModule.Blueprint,"重复记录：" + record);
                return;
            }
            BlueprintUtils.RecordList.Add(record);
        }

        public static bool ContainsRecord(string record)
        {
            return BlueprintUtils.RecordList.Contains(record);
        }
        
        public static void CreateEffectPool(int configId,int initNum,int type,GameObject originObject)
        {
            LibertyPoolMgr.GetInstance("LibertyPoolMgr").CreateEffectPool(configId,initNum,type,originObject);
        }
        
        public static void OnGuideActionComplete(int actionType, string actionParams)
        {
            TriggerGuideAction.OnActionComplete?.Invoke(actionType,actionParams);
        }

        public static void ChangeMainCharacterAnimSpeed(float speed)
        {
            var animator = BlueprintUtils.PlayerController.playerEntity.AIEntity.viewer.animator;
            if (animator)
            {
                animator.speed = speed;
            }
            var system = BlueprintUtils.PlayerController.InteractionSystem;
            if (system)
            {
                system.speed = speed;
            }
        }

        public static void PlayMainCharacterAnim(string triggerName)
        {
            var animator = BlueprintUtils.PlayerController.playerEntity.AIEntity.viewer.animator;
            if (animator)
            {
                animator.SetTrigger(triggerName);
            }
        }

        public static void PlayMainCharacterAnimByHashCode(int hashCode)
        {
            var animator = BlueprintUtils.PlayerController.playerEntity.AIEntity.viewer.animator;
            if (animator)
            {
                animator.Play(hashCode);
            }
        }

        public static void FindAllReflectionProbe()
        {
            HReflectionProbeBakeRotated.AllReflectionProbe();
        }

        public static void SwitchHangingNavUpdate(bool active)
        {
            var hangingGraph = AstarPath.active.data.FindGraphByGraphName("sidewalk_road");
                
            if (hangingGraph!=null)
            {
                hangingGraph.prohibitUpdate = !active; // 禁止挂机的寻路网格更新
            }
                
            var hangingGraph2 = AstarPath.active.data.FindGraphByGraphName("sidewalk");
            
            if (hangingGraph2!=null)
            {
                hangingGraph2.prohibitUpdate = !active; // 禁止挂机的寻路网格更新
            }
            
        }

        public static void HeroOnDeckSuccess(int heroId)
        {
            BlueprintEvents.SendHeroOnDeck(heroId);
        }

        public static void HeroDragSuccess(int heroId)
        {
            BlueprintEvents.SendHeroChangePositionSuccess(heroId);
        }
        
        public static void ResetVirtualAnalog(GameObject go)
        {
            VirtualAnalog virtualAnalog = go.GetComponentInChildren<VirtualAnalog>();
            if (virtualAnalog != null)
            {
                virtualAnalog.Reset();
            }
        }

        public static void AddTimelineInstance(string tLineName, Action<TimelineConstructor> callback = null)
        {
            TimelineConstructorMgr.GetInstance("TimelineConstructorMgr")?.AddTimelineInstance(tLineName,callback);
        }

        public static void DestroyTimelineConstructor(string tLineName)
        {
            TimelineConstructorMgr.GetInstance("TimelineConstructorMgr")?.DestroyTimelineConstructor(tLineName);
        }
        
        public static void ClearTimelines()
        {
            TimelineConstructorMgr.GetInstance("TimelineConstructorMgr")?.ClearTimelines();
        }

        public static void SetTimelineCharacterId(int characterId)
        {
            TimelineConstructorMgr.GetInstance("TimelineConstructorMgr")?.SetTimelineCharacterId(characterId);
            CityRealAiConst.MainCharacterModelName = "LeadMan";
        }

        public static void RefreshTimelineCharacterId()
        {
            TimelineConstructorMgr.GetInstance("TimelineConstructorMgr")?.RefreshTimelineCharacterId();
        }

        public static void InitAllLibertyConfigs(Action callback)
        {
            LibertyConfigManager.GetInstance().InitAllConfigs(callback);
        }

        public static void SetPhysicsLayerCollisionMatrix(string jsonPath, Action callback)
        {
            LibertyConfigManager.GetInstance().SetPhysicsLayerCollisionMatrix(jsonPath, callback);
        }

        public static bool GetStreetEventBossHP(out int hp, out int maxHp)
        {
            AIEntity bossEntity = StreetEventManager.GetInstance().GetBossEntity();
            if (bossEntity != null)
            {
                hp = bossEntity.data.hp;
                maxHp = bossEntity.propertyDataConfig.hp;
                return bossEntity.data.npcStatus == NpcStatus.Battle || bossEntity.data.npcStatus == NpcStatus.OnHit;
            }
            else
            {
                hp = 0;
                maxHp = 0;
                return false;
            }
        }

        public static bool GetStreamingMipmapsActive()
        {
            return QualitySettings.streamingMipmapsActive;
        }

        /// <summary>
        /// 递归设置GameObject层级
        /// </summary>
        /// <param name="target"></param>
        /// <param name="layer"></param>
        public static void SetLayerRecursive(GameObject target, int layer)
        {
            target.layer = layer;

            foreach (Transform child in target.transform)
            {
                SetLayerRecursive(child.gameObject, layer);
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="enable"></param>
        /// <param name="addAllCameras">是否对所有相机使用TextureStreaming</param>
        public static void SetStreamingMipmapsActive(bool enable, bool addAllCameras = false)
        {
            QualitySettings.streamingMipmapsAddAllCameras = addAllCameras;
            QualitySettings.streamingMipmapsActive = enable;
        }

        /// <summary>
        /// 设置TextureStreaming参数
        /// </summary>
        /// <param name="memoryBudget">内存预算，用于存放所有Texture的内存，串流系统会自动降低 Mipmap level来确保不超出此预算范围，根据官方介绍，其值应该设置为当Texture.streamingTextureDiscardUnusedMips=true时，略大于Texture.desiredTextureMemory的值</param>
        /// <param name="maxLevelReduction">大于等于1，小于等于7。达到memory budget后（不是拉远后），允许丢弃的最大mipmap层级数量，如果是2，意味着最多丢弃0和1级</param>
        /// <param name="renderersPerFrame"></param>
        /// <param name="maxFileIORequests"></param>
        public static void SetTextureStreamingParams(int memoryBudget, int maxLevelReduction = 7, int renderersPerFrame = 512, int maxFileIORequests = 1024)
        {
            QualitySettings.streamingMipmapsMemoryBudget = memoryBudget;
            QualitySettings.streamingMipmapsMaxLevelReduction = maxLevelReduction;
            //QualitySettings.streamingMipmapsRenderersPerFrame = renderersPerFrame;
            QualitySettings.streamingMipmapsMaxFileIORequests = maxFileIORequests;
        }

        private static float lowBudget = 10;
        private static float oriBuget;
        public static void SetTextureStreamingOnLoadingStart()
        {
            Texture.streamingTextureDiscardUnusedMips = true;
            oriBuget = QualitySettings.streamingMipmapsMemoryBudget;
            QualitySettings.streamingMipmapsMemoryBudget = lowBudget;
        }
        public static void RecoverTextureStreamingOnLoadingFinish()
        {
            QualitySettings.streamingMipmapsMemoryBudget = oriBuget;
        }


        public static void OnUIPageOpened(string pageConfigName)
        {
            UIPageLifeEvent.OnPageOpened?.Invoke(pageConfigName);
        }
        
        public static void OnUIPageClosed(string pageConfigName)
        {
            UIPageLifeEvent.OnPageClosed?.Invoke(pageConfigName);
        }

        public static bool IsCityInDay()
        {
            var dailyData = SetSunorRain.getInstance().InnerCityData;
            if (dailyData != null)
            {
                var stage = SetSunorRain.getInstance().Stage;
                bool isNight = stage == DailyStage.Night || stage == DailyStage.NightAfter;

                return !isNight;
            }

            return false;
        }
        
        // 射线检测
        public static GameObject RaycastGameObject(Vector3 origin, Vector3 direction, float maxDistance, int layerMask, string tag)
        {
            RaycastHit[] raycastHits;
            int count = PhysicsUtils.RaycastNonAlloc(out raycastHits, origin, direction, maxDistance, layerMask);
            for(int i=0; i<count; i++)
            {
                if (raycastHits[i].collider.CompareTag(tag))
                {
                    return raycastHits[i].collider.gameObject;
                }
            }

            return null;
        }
        
        public static void GameObjectPoolPreload(string path, Action callback)
        {
            GameObjectPoolManager.GetInstance().Preload(path, callback);
        }
        
        public static void GameObjectPoolPop(string path, Action<GameObject> callback, bool autoActive = true)
        {
            GameObjectPoolManager.GetInstance().Pop(path, callback, autoActive);
        }
        
        public static void GameObjectPoolPush(string path, GameObject go)
        {
            GameObjectPoolManager.GetInstance().Push(path, go);
        }
        
        public static void GameObjectPoolDestroy(string path)
        {
            GameObjectPoolManager.GetInstance().Destroy(path);
        }
        
        #region 车辆驾驶

        public static bool IsOverturn()
        {
            return BlueprintUtils.PlayerController.vehicleController.IsOverturn();
        }
        public static void ResetVehicle()
        {
            BlueprintUtils.PlayerController.vehicleController.ResetVehicle();
        }
        public static void SetVehicleMotorValue(float v)
        {
            BlueprintUtils.PlayerController.vehicleController.SetMotorValue(v);
        }
        
        public static void SetVehicleSteerValue(float v)
        {
            BlueprintUtils.PlayerController.vehicleController.SetSteerValue(v);
        }
        
        public static void SetVehicleHandbrake(float v)
        {
            BlueprintUtils.PlayerController.vehicleController.SetHandbrake(v);
        }

        public static void SetVehicleDoorHandle()
        {
            BlueprintUtils.PlayerController.vehicleBehaviourMgr.ClickDoor();
        }

        /// <summary>
        /// The speed of the vehicle in m/s.
        /// </summary>
        public static float GetVehicleSpeed()
        {
            return BlueprintUtils.PlayerController.vehicleController.GetSpeed();
        }

        #endregion

    }
}
